package com.taxshare.tools.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.AddressNotFoundException;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.City;
import com.maxmind.geoip2.record.Country;
import com.maxmind.geoip2.record.Subdivision;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * Ip地址工具类
 *
 * @author chenxd
 * @date 2019/03/18
 */
@Slf4j
@SuppressWarnings("all")
public class IpAddressUtil {

    /**
     * 地理数据库对象
     */
    private static DatabaseReader reader = null;

    /**
     * 本地IP
     */
    private static String LOCAL_IP = "10.10.0.1";

    /**
     * 淘宝接口
     */
    private static final String URL = "http://ip.taobao.com/service/getIpInfo.php";

    static {
        if (reader == null) {
            // 读取数据库内容
            try {
                //将文件中的私钥对象读出
                Resource resource = new ClassPathResource("geolite/geolite.mmdb");
                reader = new DatabaseReader.Builder(resource.getInputStream()).build();
            } catch (Exception e) {
                log.error("Ip地址工具类初始化DatabaseReader对象异常{}", e);
            }
        }
    }

    /**
     * 获取Ip地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String Xip = request.getHeader("X-Real-IP");
        String XFor = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
            //多次反向代理后会有多个ip值,第一个ip才是真实ip
            int index = XFor.indexOf(",");
            if (index != -1) {
                return XFor.substring(0, index);
            } else {
                return XFor;
            }
        }
        XFor = Xip;
        if (StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) {
            return XFor;
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getRemoteAddr();
        }
        return XFor;
    }

    /**
     * 根据Ip获取地区信息
     */
    public static Map<String, String> getAddressInfo(String ip) {
        //1.先使用geolite获取信息,如果失败则尝试通过淘宝接口获取
        Map<String, String> map = new HashMap(8);
        //内网IP
        if (StringUtils.isNotBlank(ip) && ip.startsWith("192.168")) {
            // 获取国家信息
            map.put("country", "-");
            // 获取省份
            map.put("province", "-");
            // 获取城市
            map.put("city", "内网IP");
            //ip来源
            map.put("ipOrigin", "-");
            return map;
        }
        CityResponse response;
        try {
            InetAddress ipAddress = InetAddress.getByName(ip);
            response = reader.city(ipAddress);
            // 获取国家信息
            Country country = response.getCountry();
            map.put("country", country.getNames().get("zh-CN"));
            // 获取省份
            Subdivision subdivision = response.getMostSpecificSubdivision();
            map.put("province", subdivision.getNames().get("zh-CN"));
            // 获取城市
            City city = response.getCity();
            map.put("city", city.getNames().get("zh-CN"));
            //ip来源
            map.put("ipOrigin", "geolite");
        } catch (AddressNotFoundException e) {
            return map;
        } catch (Exception e) {
            log.info("ip获取异常", e);
        }
        //2.调用淘宝接口查询信息,存在频次限制
        if (map.isEmpty() && !LOCAL_IP.equals(ip)) {
            map.clear();
            Map<String, Object> param = new HashMap<>(4);
            param.put("ip", ip);
            String resultStr = HttpClientUtil.sendGet(URL, param);
            if (StringUtils.isNotBlank(resultStr)) {
                JSONObject object = JSONUtil.parseObj(resultStr);
                if ("0".equals(object.getStr("code"))) {
                    Map<String, String> resultMap
                            = JSONUtil.toBean(object.getStr("data"), Map.class);
                    // 获取国家信息
                    map.put("country", resultMap.get("country"));
                    // 获取省份
                    map.put("province", resultMap.get("region"));
                    // 获取城市
                    map.put("city", resultMap.get("city"));
                    //ip来源
                    map.put("ipOrigin", "taob");
                }
            }
        }
        return map;
    }

}
